JoinRowConsumer.java
package org.codefilarete.stalactite.engine.runtime.load;
import java.util.Set;
import org.codefilarete.stalactite.engine.runtime.load.EntityJoinTree.JoinType;
import org.codefilarete.stalactite.engine.runtime.load.EntityTreeInflater.TreeInflationContext;
import org.codefilarete.stalactite.sql.ddl.structure.Key;
import org.codefilarete.stalactite.sql.result.ColumnedRow;
/**
* The JoinRowConsumer interface defines a contract for consuming rows from a database result set
* as part of an object graph construction process. This mechanism is used to handle hierarchical
* joins and populate corresponding object nodes in an entity tree during the processing.
*/
public interface JoinRowConsumer {
JoinNode<?, ?> getNode();
default void beforeRowConsumption(TreeInflationContext context) {
}
default void afterRowConsumption(TreeInflationContext context) {
}
interface RootJoinRowConsumer<C, I> extends JoinRowConsumer {
EntityReference<C, I> createRootInstance(ColumnedRow row, TreeInflationContext context);
}
/**
* A container class that holds a reference to an entity and its corresponding identifier.
* Made to avoid relying on entity equals/hashcode but on identifier equality, because
* that's one of Stalactite principles: avoid implementing equals/hashCode on entities, but
* make it mandatory for identifier because it's more logical for them, whereas entity
* equality may rely on business rules and ORM shouldn't force it to base it on identifier.
*
* @param <C> the type of the entity
* @param <I> the type of the identifier associated with the entity
*/
class EntityReference<C, I> {
private final C entity;
private final I identifier;
public EntityReference(C entity, I identifier) {
this.entity = entity;
this.identifier = identifier;
}
public C getEntity() {
return entity;
}
public I getIdentifier() {
return identifier;
}
}
/**
* Interface to implement when a {@link JoinRowConsumer} needs to provide the next join consumer (among the ones he owns): in case of polymorphism,
* we need to choose the right next branch that fills the created entity. This interface is made to provide the next sub-consumer for the next
* iteration.
* @author Guillaume Mary
*/
interface ForkJoinRowConsumer extends JoinRowConsumer {
JoinRowConsumer giveNextConsumer();
}
/**
* Interface to implement when a {@link RootJoinRowConsumer} needs to skip some joins he owns: by default {@link EntityTreeInflater} iterates
* over all consumers returned by a {@link RootJoinRowConsumer} but, in case of polymorphism, we need to skip the branches that are not implied
* in the process of instance creation. This interface is made to provide the sub-consumers to exclude from next iteration.
* @author Guillaume Mary
*/
interface ExcludingJoinRowConsumer<C, I> extends RootJoinRowConsumer<C, I> {
//deadBranches
Set<JoinRowConsumer> giveExcludedConsumers();
}
}